#ifndef U2DataStreamFileHandle_H
#define U2DataStreamFileHandle_H

#include "U2PreRequest.h"
#include "U2DataStream.h"


U2EG_NAMESPACE_BEGIN


class _U2Share U2DataStreamMemory : public U2DataStream
{
public:
	
	/** Wrap an existing memory chunk in a stream.
	@param pMem Pointer to the existing memory
	@param size The size of the memory chunk in bytes
	@param freeOnClose If true, the memory associated will be destroyed
		when the stream is destroyed. Note: it's important that if you set
		this option to true, that you allocated the memory using OGRE_ALLOC_T
		with a category of MEMCATEGORY_GENERAL ensure the freeing of memory 
		matches up.
	@param readOnly Whether to make the stream on this memory read-only once created
	*/
	U2DataStreamMemory(void* pMem, size_t size, bool freeOnClose = false, bool readOnly = false, Endian endian = ENDIAN_NATIVE);
	
	/** Wrap an existing memory chunk in a named stream.
	@param name The name to give the stream
	@param pMem Pointer to the existing memory
	@param size The size of the memory chunk in bytes
	@param freeOnClose If true, the memory associated will be destroyed
		when the stream is destroyed. Note: it's important that if you set
		this option to true, that you allocated the memory using OGRE_ALLOC_T
		with a category of MEMCATEGORY_GENERAL ensure the freeing of memory 
		matches up.
	@param readOnly Whether to make the stream on this memory read-only once created
	*/
	U2DataStreamMemory(const U2String& name, void* pMem, size_t size, 
			bool freeOnClose = false, bool readOnly = false, Endian endian = ENDIAN_NATIVE);

	/** Create a stream which pre-buffers the contents of another stream.
	@remarks
		This constructor can be used to intentionally read in the entire
		contents of another stream, copying them to the internal buffer
		and thus making them available in memory as a single unit.
	@param sourceStream Another U2DataStream which will provide the source
		of data
	@param freeOnClose If true, the memory associated will be destroyed
		when the stream is destroyed.
	@param readOnly Whether to make the stream on this memory read-only once created
	*/
	U2DataStreamMemory(U2DataStream& sourceStream, 
			bool freeOnClose = true, bool readOnly = false);
	
	/** Create a stream which pre-buffers the contents of another stream.
	@remarks
		This constructor can be used to intentionally read in the entire
		contents of another stream, copying them to the internal buffer
		and thus making them available in memory as a single unit.
	@param sourceStream Weak reference to another U2DataStream which will provide the source
		of data
	@param freeOnClose If true, the memory associated will be destroyed
		when the stream is destroyed.
	@param readOnly Whether to make the stream on this memory read-only once created
	*/
	U2DataStreamMemory(U2DataStreamPtr& sourceStream, 
			bool freeOnClose = true, bool readOnly = false);

	/** Create a named stream which pre-buffers the contents of 
		another stream.
	@remarks
		This constructor can be used to intentionally read in the entire
		contents of another stream, copying them to the internal buffer
		and thus making them available in memory as a single unit.
	@param name The name to give the stream
	@param sourceStream Another U2DataStream which will provide the source
		of data
	@param freeOnClose If true, the memory associated will be destroyed
		when the stream is destroyed.
	@param readOnly Whether to make the stream on this memory read-only once created
	*/
	U2DataStreamMemory(const U2String& name, U2DataStream& sourceStream, 
			bool freeOnClose = true, bool readOnly = false);

    /** Create a named stream which pre-buffers the contents of 
    another stream.
    @remarks
    This constructor can be used to intentionally read in the entire
    contents of another stream, copying them to the internal buffer
    and thus making them available in memory as a single unit.
    @param name The name to give the stream
    @param sourceStream Another U2DataStream which will provide the source
    of data
    @param freeOnClose If true, the memory associated will be destroyed
    when the stream is destroyed.
	@param readOnly Whether to make the stream on this memory read-only once created
    */
    U2DataStreamMemory(const U2String& name, const U2DataStreamPtr& sourceStream, 
        bool freeOnClose = true, bool readOnly = false);

    /** Create a stream with a brand new empty memory chunk.
	@param size The size of the memory chunk to create in bytes
	@param freeOnClose If true, the memory associated will be destroyed
		when the stream is destroyed.
	@param readOnly Whether to make the stream on this memory read-only once created
	*/
	U2DataStreamMemory(size_t size, bool freeOnClose = true, bool readOnly = false, Endian endian = ENDIAN_NATIVE);
	/** Create a named stream with a brand new empty memory chunk.
	@param name The name to give the stream
	@param size The size of the memory chunk to create in bytes
	@param freeOnClose If true, the memory associated will be destroyed
		when the stream is destroyed.
	@param readOnly Whether to make the stream on this memory read-only once created
	*/
	U2DataStreamMemory(const U2String& name, size_t size, 
			bool freeOnClose = true, bool readOnly = false, Endian endian = ENDIAN_NATIVE);

	~U2DataStreamMemory();

	/** Get a pointer to the start of the memory block this stream holds. */
	u2uchar* getPtr(void) { return mData; }
	
	/** Get a pointer to the current position in the memory block this stream holds. */
	u2uchar* getCurrentPtr(void) { return mPos; }
	
	/** @copydoc U2DataStream::read
	*/
	size_t read(void* buf, size_t count);

	/** @copydoc U2DataStream::write
	*/
	size_t write(const void* buf, size_t count);

	/** @copydoc U2DataStream::readLine
	*/
	size_t readLine(char* buf, size_t maxCount, const U2String& delim = "\n");
	
	/** @copydoc U2DataStream::skipLine
	*/
	size_t skipLine(const U2String& delim = "\n");

	/** @copydoc U2DataStream::skip
	*/
	void skip(long count);

	/** @copydoc U2DataStream::seek
	*/
    void seek( size_t pos );
	
	/** @copydoc U2DataStream::tell
	*/
    size_t tell(void) const;

	/** @copydoc U2DataStream::eof
	*/
    bool eof(void) const;

    /** @copydoc U2DataStream::close
    */
    void close(void);

	/** Sets whether or not to free the encapsulated memory on close. */
	void setFreeOnClose(bool free) { mFreeOnClose = free; }

protected:
    /// Pointer to the start of the data area
    u2uchar* mData;
    /// Pointer to the current position in the memory
    u2uchar* mPos;
    /// Pointer to the end of the memory
    u2uchar* mEnd;
    /// Do we delete the memory on close
    bool mFreeOnClose;
};


/** Shared pointer to allow memory data streams to be passed around without
worrying about deallocation
*/
typedef U2SharedPtr<U2DataStreamMemory> U2DataStreamMemoryPtr;



U2EG_NAMESPACE_END

#endif